import patchVnode from './patchVnode.js'
import createElement from './createElement.js'
// 判断是否是同一个虚拟节点
function checkSameVnode (a, b) {
	console.log(a, b)
	return a.sel === b.sel && a.key === b.key
}

export default function updateChildren (parentElm, oldCh, newCh) {
	console.log('产生')
	// 旧前
	let oldStartIdx = 0
	// 新前
	let newStartIdx = 0
	// 旧后
	let oldEndIdx = oldCh.length - 1
	// 新后
	let newEndIdx = newCh.length - 1
	// 旧前节点
	let oldStartVnode = oldCh[0]
	// 旧后节点
	let oldEndVnode = oldCh[oldEndIdx]
	// 新前节点
	let newStartVnode = newCh[0]
	// 新后节点
	let newEndVnode = newCh[newEndIdx]
	// 缓存
	let keyMap = null
	// 开始while
	while (oldEndIdx >= oldStartIdx && newEndIdx >= newStartIdx) {
		// 首先不是判断1234的命中，而是要略过已经加undefined标记的节点
		if (oldStartVnode === undefined || oldCh[oldStartIdx] === undefined) {
			oldStartVnode = oldCh[++oldStartIdx]
		} else if (oldEndVnode === undefined || oldCh[oldEndIdx] === undefined) {
			oldEndVnode = oldCh[--oldEndIdx]
		} else if (checkSameVnode(oldStartVnode, newStartVnode)) {
			// 新前和旧前
			patchVnode(oldStartVnode, newStartVnode)
			// ++oldStartIdx表示先让oldStartIdx后移再使用
			oldStartVnode = oldCh[++oldStartIdx]
			newStartVnode = newCh[++newStartIdx]
		} else if (checkSameVnode(oldEndVnode, newEndVnode)) {
			// 新后和旧后
			patchVnode(oldEndVnode, newEndVnode)
			oldEndVnode = oldCh[--oldEndIdx]
			newEndVnode = newCh[--newEndIdx]
		} else if (checkSameVnode(oldStartVnode, newEndVnode)) {
			// 新后和旧前
			patchVnode(oldStartVnode, newEndVnode)
			// 当新后与旧前命中的时候，移动节点，移动新后指向的节点到老节点旧后的后面
			// 如何移动节点？只要你插入一个已经在DOM树上的节点，他就会被移动
			// oldEndVnode.elm.nextSibling 是老节点的后面
			parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling)
			oldStartVnode = oldCh[++oldStartIdx]
			newEndVnode = newCh[--newEndIdx]
		} else if (checkSameVnode(oldEndVnode, newStartVnode)) {
			// 新前和旧后
			patchVnode(oldEndVnode, newStartVnode)
			// 当新前与旧后命中的时候，移动节点，移动新前指向的节点到老节点旧前的前面
			// 如何移动节点？只要你插入一个已经在DOM树上的节点，他就会被移动
			parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm)
			oldEndVnode = oldCh[--oldEndIdx]
			newStartVnode = newCh[++newStartIdx]
		} else {
			// 四种都没有命中
			// 寻找key的map
			if (!keyMap) {
				keyMap = {}
				for (let i = oldStartIdx; i <= oldEndIdx; i++) {
						const key = oldCh[i].key
						if (key !== undefined) {
							keyMap[key] = i
						}
				}
			}
			// 寻找当前newStartIdx这项在keyMap中映射的位置序号
			const idxInOld = keyMap[newStartVnode.key]
			if (idxInOld === undefined) {
				// 判断，如果idxInOld是undefined就表示它是全新的项
				// 被加入的项newStartVnode现在目前不是真正DOM节点
				// 目前将新加的项都加在旧前的前面不考虑旧后
				parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm)
			} else {
				// 如果不是undefined，不是全新的项，而要移动
				const elmToMove = oldCh[idxInOld]
				console.log(elmToMove, newStartVnode)
				patchVnode(elmToMove, newStartVnode)
				// 把这项设置为undefined，表示我已经处理此项
				oldCh[idxInOld] = undefined
				// 移动，调用insertBefore将此新节点移动到老节点旧前之前
				// 因为那是已经处理过的节点
				// 简易版其他种类情况不考虑
				parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm)
			}
			// 指针下移，只移动新前
			newStartVnode = newCh[++newStartIdx]
		}
	}
	// 继续看看有没有剩余,循环结束start还是比old小
	if (newStartIdx <= newEndIdx) {
		// 插入的标杆 null表示最后，不会报错直接插入到最后面
		const before = oldCh[oldEndIdx + 1] == null ? null : oldCh[oldEndIdx + 1].elm
		for (let i = newStartIdx; i <= newEndIdx; i++) {
			// insertBefore方法可以自动识别null，如果是null就会自动排到队尾
			parentElm.insertBefore(createElement(newCh[i]), before)
		}
	} else if (oldStartIdx <= oldEndIdx) {
		for (let i = oldStartIdx; i <= oldEndIdx; i++) {
			// 在这里禁止使用createElement(oldCh[i])代替oldCh[i].elm
			// 因为经过createElement(oldCh[i])处理节点虽然与oldCh[i].elm结果相同，但是此时不是同一个子节点无法删除
			// 这里判断的原因是它循环已经脱离while，没有判断老节点undefined的能力
			// undefined相当于false
			if (oldCh[i]) {
				parentElm.removeChild(oldCh[i].elm)
			}
		}
	}
}